#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>

#define BUFFSIZE 5096

int main(int argc, char *argv[]) {
  int sendlen, receivelen, sock;
  char buffer[BUFFSIZE];
  char level_id[16];
  char password[16];
  struct sockaddr_in sendsocket, receivesocket;
  struct termios oldt, newt;

  int ret = 0;

  if((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
    perror("socket allocation");
    return -1;
  }

  // Client socket
  memset(&receivesocket, 0, sizeof(receivesocket));
  receivesocket.sin_family = AF_INET;
  receivesocket.sin_addr.s_addr = htonl(INADDR_ANY);
  receivesocket.sin_port = htons(9999);

  receivelen = sizeof(receivesocket);
  if(bind(sock, (struct sockaddr *)&receivesocket, receivelen) < 0) {
    perror("binding");
    return -1;
  }

  // Kernel socket
  memset(&sendsocket, 0, sizeof(sendsocket));
  sendsocket.sin_family = AF_INET;
  sendsocket.sin_addr.s_addr = inet_addr("127.0.0.1");
  sendsocket.sin_port = htons(5555);

  // Set environment to not echo credential entry
  tcgetattr(STDIN_FILENO, &oldt);
  newt = oldt;
  newt.c_lflag &= ~ECHO;
  tcsetattr(STDIN_FILENO, TCSANOW, &newt);

  printf("Enter credentials:");
  printf("\nLevel ID: ");
  scanf("%s", level_id);
  printf("\nPassword: ");
  scanf("%s", password);
  printf("\n");

  // Return to original environment
  tcsetattr(STDIN_FILENO, TCSANOW, &oldt);

  // Send level_id and password to Kernel
  memcpy(buffer, "l:", 2);
  memcpy(buffer+2, level_id, strlen(level_id) + 1);
  sendlen = strlen(buffer) + 1;
  if(sendto(sock, buffer, sendlen, 0, (struct sockaddr *)&sendsocket,
	    sizeof(sendsocket)) != sendlen) {
    perror("send error");
    return -1;
  }
  memcpy(buffer, "p:", 2);
  memcpy(buffer+2, password, strlen(password) + 1);
  sendlen = strlen(buffer) + 1;
  if(sendto(sock, buffer, sendlen, 0, (struct sockaddr *)&sendsocket,
	    sizeof(sendsocket)) != sendlen) {
    perror("send error");
    return -1;
  }
  memcpy(buffer, "open", strlen("open") + 1);
  sendlen = strlen(buffer) + 1;
  if(sendto(sock, buffer, sendlen, 0, (struct sockaddr *)&sendsocket,
	    sizeof(sendsocket)) != sendlen) {
    perror("send error");
    return -1;
  }
  
  return 0;
}
